/*!
 * \file cics_core.h
 *
 * \brief CICS模块主文件
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.
 *
 * \version 1.0
 * \author songbb
 * \date 2015/10/07
 *
 */

#ifndef __CICS_CORE_H_
#define __CICS_CORE_H_

#include "frlist.h"
#include "frhash2.h"
#include "frstr.h"

#include "conntrack.h"
#include "module.h"
#include "frbyte_buffer.h"

#define APM_CICS_REQ_TYPE_MAXLEN 16     //!< ReqType字符串最大长度

/*! @brief CICS协议通用包头 */
typedef struct __st_cics_header
{
    unsigned int ui_flow_version;                   /*!< Flow版本 */
    unsigned int ui_flow_type;                      /*!< Flow类型 */
    unsigned int ui_msg_id;                         /*!< MessageID */
    int i_gateway_rc;                               /*!< Gateway的ReturnCode */
    char arr_req_type[APM_CICS_REQ_TYPE_MAXLEN];    /*!< RequestType */
    unsigned int ui_header_len;                     /*!< 消息头长度 */
    unsigned int ui_data_which_follows;             /*!< 消息体长度 */
} Cics_header;

/*! @brief L7session_cics 用于存放Cics私有的session数据，对应L7_session的p_session_private变量 */
typedef struct __st_L7session_cics
{
    char *p_server;                                         /*!< Server信息 */
    char *p_userid;                                         /*!< UserID */

    char *p_encoding;                                       /*!< 字符串Encoding */
} L7session_cics;

/*! @brief 分片的状态 */
typedef enum __em_fragment_state {
    APM_CICS_FRAGMENT_INIT,                     //!< 初始化
    APM_CICS_FRAGMENT_NEED_NEXT_REQ_PACKET,     //!< 需要下一个请求包
    APM_CICS_FRAGMENT_NEED_NEXT_RESP_PACKET     //!< 需要下一个响应包
} Cics_fragment_state;

/*! @brief REQTYPE类型 */
typedef enum __em_req_type {
    APM_CICS_REQTYPE_UNKNOWN,       //!< 对应UNKNOWN
    APM_CICS_REQTYPE_BASE,          //!< 对应BASE
    APM_CICS_REQTYPE_ECI,           //!< 对应ECI
    APM_CICS_REQTYPE_ESI,           //!< 对应ESI
    APM_CICS_REQTYPE_EPI,           //!< 对应EPI
    APM_CICS_REQTYPE_AUTH,          //!< 对应AUTH
    APM_CICS_REQTYPE_XA,            //!< 对应XA
    APM_CICS_REQTYPE_CICSCP         //!< 对应CICSCP
} Cics_req_type;

/*! @brief CICS数据包 */
typedef struct __st_L7_cics_packet
{
    Cics_fragment_state fragment_state; //!< 当前的分片状态
    Frbyte_Packet *p_st_packet;         //!< 组包完成的数据
    unsigned int ui_header_len;         //!< Header长度
    unsigned int ui_length;             //!< 数据包长度
    unsigned int ui_len_to_read;        //!< 还需要从下一个payload中读取多少个字节
    struct timeval st_timestamp_first;  //!< 第一个请求的分片包的时间
    struct timeval st_timestamp_last;   //!< 最后一个请求的分片包的时间
    unsigned long ul_skip_len;          //!< 需要跳过的长度
    unsigned int ui_flow_version;       //!< Flow版本
    unsigned int ui_flow_type;          //!< Flow类型
    unsigned int ui_msg_id;             //!< MessageID
    int i_gateway_rc;                   //!< Gateway的ReturnCode
    Cics_req_type em_req_type;          //!< ReqType
} L7_cics_packet;

/*! @brief CICS交易信息 */
typedef struct __st_L7_cics_stmt
{
    unsigned int ui_msg_id;                 //!< MessageID
    unsigned int ui_extend_mode;            //!< ExtendMode
    int i_b_callback_exists;                //!< 是否存在callback
    struct timeval st_req_end_timestamp;    //!< 请求的结束时间戳
    struct timeval st_resp_start_timestamp; //!< 响应的开始时间戳
    unsigned long ul_resp_server_time_us;   //!< 响应的Server时间
} L7_cics_stmt;

/*! @brief CICS私有结构体 */
typedef struct __st_L7session_cics_private
{
    L7session_cics *p_st_sess;           //!< session数据
    Frhash_header *p_hash_stmt;          //!< 按message_id建立hash
    L7_cics_packet *p_st_cics_packet;    //!< 当前处理中的Cics数据包
    Frlist_header *p_report_comm;        //!< 用于临时存储report的公共部分数据
    Frlist_header *p_report_req;         //!< 用于临时存储report的请求部分数据
    L7_session *p_st_session;            //!< 指向父级的L7_session结构体
} L7session_cics_private;

/*!
 * 判断当前数据链路是否是CICS协议的
 *
 * \param p_st_conn        (ct信息)
 * \param p_st_packet     (协议分析入力数据)
 *
 * \return 参照module.h中APM_L7_IS_的定义
 *
 */
int cics_detect(Conntrack *p_st_conn
            , Apm_packet *p_st_packet);

/*!
 * CICS协议解析入口
 *
 * \param p_st_conn             (ct信息)
 * \param p_st_packet          (协议分析入力数据)
 * \param p_st_hash_report      (保存Frreport_data)
 *
 * \return 参照module.h中APM_L7_ANALYZE_的定义
 *
 */
int cics_analyze(Conntrack *p_st_conn
                , Apm_packet *p_st_packet
                , Frhash_header *p_st_hash_report);

/*!
 * 释放CICS private数据
 *
 * \param p_st_session_private_in        (CICS的私有信息)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
int cics_session_destory(void *p_st_session_private_in);

#endif
